package com.ruoyi.learn.java.design.pattern.behavior;
import java.util.ArrayList;
import java.util.List;

/**
 * 文本编辑器类，同时集成了发起人(Originator)、备忘录(Memento)和管理者(Caretaker)的角色。
 * 这是一个将备忘录模式所有组件封装在一个类中的例子。
 */
 class TextEditor {

    // ==== 发起人 (Originator) 的状态 ====
    private String text = "";

    // ==== 管理者 (Caretaker) 的职责：管理备忘录列表 ====
    private final List<Memento> history = new ArrayList<>();
    private int currentHistoryIndex = -1; // 指向当前状态在历史记录中的位置，-1 表示无状态

    // ==== 备忘录 (Memento) 类 (作为内部类) ====
    // 内部类可以访问外部类的私有成员，但这里我们只存储状态快照。
    private static class Memento {
        private final String text;
        // 可以添加更多需要保存的状态字段

        public Memento(String text) {
            this.text = text;
        }

        // 提供给发起人恢复状态
        public String getText() {
            return text;
        }
    }

    // ==== 发起人 (Originator) 的操作方法 ====

    public void setText(String text) {
        this.text = text;
        System.out.println("文本已设置: \"" + text + "\"");
        // 文本更改后，通常需要保存新状态（可选，取决于需求）
        // 这里我们选择在需要时手动调用 saveState()，模拟更精确的控制
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return "TextEditor{text='" + text + "'}";
    }

    // ==== 备忘录 (Memento) 和 管理者 (Caretaker) 的交互方法 ====

    /**
     * 保存当前状态到历史记录。
     * 如果当前不在历史记录的末尾（例如执行了撤销后又输入了新内容），
     * 则丢弃当前点之后的所有历史记录。
     */
    public void saveState() {
        Memento memento = new Memento(this.text);

        // 如果当前不在历史末尾，删除之后的记录（分支处理）
        if (currentHistoryIndex < history.size() - 1) {
            history.subList(currentHistoryIndex + 1, history.size()).clear();
        }

        history.add(memento);
        currentHistoryIndex = history.size() - 1;
        System.out.println("状态已保存。历史记录总数: " + history.size());
    }

    /**
     * 撤销到上一个状态。
     * @return 如果成功撤销返回 true，否则返回 false（如无历史记录）
     */
    public boolean undo() {
        if (currentHistoryIndex > 0) {
            currentHistoryIndex--;
            Memento memento = history.get(currentHistoryIndex);
            this.text = memento.getText(); // 发起人使用备忘录恢复状态
            System.out.println("已撤销到: \"" + text + "\"");
            return true;
        } else if (currentHistoryIndex == 0) {
            // 回退到第一个状态
            Memento memento = history.get(0);
            this.text = memento.getText();
            currentHistoryIndex = -1; // 或者保持为0，取决于设计，这里设为-1表示无有效前一个状态
            System.out.println("已撤销到初始状态: \"" + text + "\"");
            return true;
        }
        System.out.println("无法撤销：无更多历史记录。");
        return false;
    }

    /**
     * 重做到下一个状态（在撤销之后使用）。
     * @return 如果成功重做返回 true，否则返回 false
     */
    public boolean redo() {
        if (currentHistoryIndex < history.size() - 1 && history.size() > 0) {
            currentHistoryIndex++;
            Memento memento = history.get(currentHistoryIndex);
            this.text = memento.getText();
            System.out.println("已重做到: \"" + text + "\"");
            return true;
        }
        System.out.println("无法重做：无更多重做记录。");
        return false;
    }

    /**
     * 清空所有历史记录
     */
    public void clearHistory() {
        history.clear();
        currentHistoryIndex = -1;
        System.out.println("历史记录已清空。");
    }

    /**
     * 获取历史记录大小（用于测试或显示）
     */
    public int getHistorySize() {
        return history.size();
    }

    /**
     * 获取当前在历史记录中的位置
     */
    public int getCurrentHistoryIndex() {
        return currentHistoryIndex;
    }
}
/**
 * 演示将备忘录模式整合到单个类中的用法。
 */
public class SingleClassMementoDemo {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();

        // 初始状态
        editor.setText("Hello");
        editor.saveState(); // 保存状态 1

        editor.setText("Hello World");
        editor.saveState(); // 保存状态 2

        editor.setText("Hello World!");
        editor.saveState(); // 保存状态 3

        System.out.println("\n当前状态: " + editor);
        System.out.println("历史记录总数: " + editor.getHistorySize());

        // 撤销
        editor.undo(); // 回到 "Hello World"
        editor.undo(); // 回到 "Hello"

        System.out.println("两次撤销后: " + editor);

        // 重做
        editor.redo(); // 重做到 "Hello World"
        System.out.println("重做一次后: " + editor);

        // 在撤销后输入新内容，会创建新的分支
        editor.setText("Hello Universe");
        editor.saveState(); // 保存新分支的状态

        System.out.println("\n输入新内容并保存后: " + editor);
        System.out.println("历史记录总数: " + editor.getHistorySize());

        // 再次撤销
        editor.undo(); // 应该回到 "Hello" (上一个保存点)
        System.out.println("再次撤销后: " + editor);

        // 尝试重做 - 因为新分支覆盖了旧历史，这里应该无法重做
        editor.redo(); // 可能失败，取决于实现
    }
}
